package org.remote;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import java.util.Map.Entry;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.ParseException;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpClientConnection;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestExecutor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestTargetHost;
import org.apache.http.protocol.RequestUserAgent;
import org.apache.http.util.EntityUtils;
import org.util.Util;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.os.Environment;

import android.util.Log;

public class RemoteContentProvider {
	private static final String INSERT="insert";
	private static final String DELETE="delete";
	private static final String QUERY="query";
	private static final String UPDATE="update";
	
	private String serverAddress;
	private int serverPort;
	private HttpParams params;
	private DefaultHttpClientConnection conn;
	private HttpHost host;
	private HttpRequestExecutor httpexecutor;
	private BasicHttpProcessor httpproc;
	private HttpContext context;
	
	public RemoteContentProvider(String address,int port){
		this.serverAddress=address;
		this.serverPort=port;
		params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, "UTF-8");
        HttpProtocolParams.setUserAgent(params, "HttpComponents/1.1");
        HttpProtocolParams.setUseExpectContinue(params, true);
        
        httpproc = new BasicHttpProcessor();
        httpproc.addInterceptor(new RequestContent());
        httpproc.addInterceptor(new RequestTargetHost());
        // Recommended protocol interceptors
        httpproc.addInterceptor(new RequestConnControl());
        httpproc.addInterceptor(new RequestUserAgent());
        httpproc.addInterceptor(new RequestExpectContinue());
       
        
        httpexecutor = new HttpRequestExecutor();

        context = new BasicHttpContext(null);
        
        host = new HttpHost(serverAddress, serverPort);
        
        conn = new DefaultHttpClientConnection();
        ConnectionReuseStrategy connStrategy = new DefaultConnectionReuseStrategy();

        context.setAttribute(ExecutionContext.HTTP_CONNECTION, conn);
        context.setAttribute(ExecutionContext.HTTP_TARGET_HOST, host);


	}
	
	
	
	public ArrayList<HashMap<String, String>> query(Uri contentUri,String[] projection,String where,String[] params,String sortOrder) throws HttpException, IOException, ParserConfigurationException, SAXException{
		
		String value="query ";
		if(projection!=null){
			value=value.concat(new Integer(projection.length).toString()+",");
			value=value.concat(Util.stringArrayToString(projection));
		}
		else{
			value=value.concat("null,");
		}
		if(where!=null){
			value=value.concat(where+",");
		}
		else{
			value=value.concat("null,");
		}
		if(params!=null){
			value=value.concat(new Integer(params.length).toString()+",");
			value=value.concat(Util.stringArrayToString(params));
		}
		else{
			value=value.concat("null,");
		}
		if(sortOrder!=null){
			value=value.concat(sortOrder+",");
		}
		else{
			value=value.concat("null,");
		}
		StringEntity entity=new StringEntity(value);
		HttpResponse response=makeRequest(contentUri, entity);
		
		
		HttpEntity fileEntity=response.getEntity();
		
		
		
		File file=new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/contact.xml");
		if(!file.exists()) file.createNewFile();
		else file.delete();
		InputStream in=fileEntity.getContent();
		
		OutputStream out=new FileOutputStream(file);
//		Log.d("client", EntityUtils.toString(fileEntity));
		int len=0;
		byte[] buf=new byte[1024];
		while((len=in.read(buf))>0){
			Log.d("client", "dentro il while");
			out.write(buf,0,len);
		}
		Log.d("client", "dopo il while");
		out.close();
		fileEntity.consumeContent();
		
		
		
		ArrayList<HashMap<String, String>> list=new ArrayList<HashMap<String,String>>();
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		Document dom=null;
		
			DocumentBuilder builder = factory.newDocumentBuilder();
			dom = builder.parse(file);
		
		
		
       NodeList items = dom.getElementsByTagName("contatto");

        for (int i=0;i<items.getLength();i++){
        	HashMap<String, String> hashMap=new HashMap<String, String>();
            Node item = items.item(i);
            NamedNodeMap n=item.getAttributes();
            for(int j=0;j<n.getLength();j++){
            	Node att=n.item(j);
            	hashMap.put(att.getNodeName(), att.getNodeValue());
            }
            
            list.add(hashMap);
        }
		return list;
	}
	
	
	
	
	public Uri insert(Uri contentUri,ContentValues values) throws HttpException, IOException {
		String value=Util.contentValuesToString(values);
		String operation="insert";
		operation=operation.concat(" ").concat(value);
		String uri=null;
		
			StringEntity entity=new StringEntity(operation);
			HttpResponse response=makeRequest(contentUri, entity);
			uri = EntityUtils.toString(response.getEntity());
		
        return Uri.parse(uri);
        
	}
	public int delete(Uri contentUri,String where,String[] whereArgs) throws HttpException, IOException {
		String operation="delete";
		operation=operation.concat(operation).concat(" ");
		if(where!=null){
			operation=operation.concat(where).concat(",");
		}
		else operation=operation.concat("null,");
		if(whereArgs!=null){
			operation=operation.concat(new Integer(whereArgs.length).toString()+",");
			for(int i=0;i<whereArgs.length;i++){
				operation=operation.concat(whereArgs[i]).concat(",");
			}
		}
		else operation=operation.concat("null,");
		StringEntity entity=new StringEntity(operation);
		HttpResponse response=makeRequest(contentUri, entity);
        String ret=EntityUtils.toString(response.getEntity());
		
		return Integer.parseInt(ret);
	}
	public int update(Uri contentUri,ContentValues values,String where,String[] params) throws HttpException, IOException{
		String value="update ";
		Set<Entry<String, Object>> valueSet = values.valueSet();
		value=value.concat(new Integer(valueSet.size()).toString()+",");
		value=value.concat(Util.contentValuesToString(values));
		if(where!=null){
			value=value.concat(where+",");
		}
		else{
			value=value.concat("null,");
		}
		if(params!=null){
			value=value.concat(new Integer(params.length).toString()+",");
			value=value.concat(Util.stringArrayToString(params));
		}
		else{
			value=value.concat("null,");
		}
		Log.d("remote",value);
		StringEntity entity=new StringEntity(value);
		HttpResponse response=makeRequest(contentUri, entity);
		String ret=EntityUtils.toString(response.getEntity());
		
		
		return Integer.parseInt(ret);
	}
	
	
	private HttpResponse makeRequest(Uri contentUri,HttpEntity entity) throws HttpException, IOException {
		if (!conn.isOpen()) {
            try {
				Socket socket = new Socket(host.getHostName(), host.getPort());
				conn.bind(socket, params);
			} catch (UnknownHostException e) {
				Log.d("remote ", e.toString());
				e.printStackTrace();
			} catch (IOException e) {
				Log.d("remote ", e.toString());
				e.printStackTrace();
			}
        }
        final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("POST",contentUri.toString() );
        request.setEntity(entity);//body
        request.setParams(params);
        HttpResponse response=null;
		
			httpexecutor.preProcess(request, httpproc, context);
			response = httpexecutor.execute(request, conn, context);
			response.setParams(params);
			httpexecutor.postProcess(response, httpproc, context);
		
		
		
        return response;
	}

}
